﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Text.RegularExpressions;
using System.IO;

namespace ihongma.WebData
{
    public static class HttpRequestHelper
    {
        /// <summary>
        /// 取得字符里的Dom元素 不包含元素属性
        /// </summary>
        /// <param name="orgStr"></param>
        /// <param name="domElem"></param>
        /// <returns></returns>
        public static List<string> GetDomElem(string orgStr, string domElem)
        {
            List<string> matchList = new List<string>();
            string regStr = string.Format("<{0}[^>]*?>[\\s\\S]+?<\\/{0}>", domElem);
            try
            {
                Regex regex = new Regex(regStr, RegexOptions.Compiled | RegexOptions.IgnoreCase);
                MatchCollection matches = regex.Matches(orgStr);
                StringBuilder sb = new StringBuilder();
                foreach (Match match in matches)
                {
                    matchList.Add(match.Value);
                }
            }
            catch (Exception ex)
            {
                matchList.Add(ex.Message);
            }
            return matchList;
        }

        /// <summary>
        /// 取得字符里的Dom元素 包含元素属性 如：class="aa"
        /// </summary>
        /// <param name="orgStr"></param>
        /// <param name="tagName"></param>
        /// <param name="tagValue"></param>
        /// <returns></returns>
        public static List<string> GetDomElemByAttr(string orgStr, string tagName, string tagValue)
        {
            List<string> matchList = new List<string>();
            string regStr = string.Format(@"<(?<HtmlTag>[\w]+)[^>]*\s{0}=(?<Quote>[""']?){1}(?(Quote)\k<Quote>)[""']?[^>]*>((?<Nested><\k<HtmlTag>[^>]*>)|</\k<HtmlTag>>(?<-Nested>)|[\s\S]*?)*</\k<HtmlTag>>", tagName.ToLower(), tagValue);
            try
            {
                Regex regex = new Regex(regStr, RegexOptions.Compiled | RegexOptions.IgnoreCase);
                MatchCollection matches = regex.Matches(orgStr);
                StringBuilder sb = new StringBuilder();
                foreach (Match match in matches)
                {
                    matchList.Add(match.Value);
                }
            }
            catch (Exception ex)
            {
                matchList.Add(ex.Message);
            }
            return matchList;
        }

        /// <summary>
        /// 取得字符里的A元素键值对  [name，url]
        /// </summary>
        /// <param name="orgStr"></param>
        /// <param name="domElem"></param>
        /// <returns></returns>
        public static Dictionary<string, string> GetDomElem_A(string orgStr)
        {
            Dictionary<string, string> matchList = new Dictionary<string, string>();
            string regStr1 = "<a[^>]*? href=[\"'](?<url>[^\"']*?)[\"'][^>]*?>(?<text>[\\w\\W]*?)</a>";
            try
            {
                Regex regex = new Regex(regStr1, RegexOptions.Compiled | RegexOptions.IgnoreCase);
                MatchCollection matches = regex.Matches(orgStr);
                StringBuilder sb = new StringBuilder();
                foreach (Match match in matches)
                {
                    string key = match.Value;
                    if (!matchList.ContainsKey(key))
                    {
                        matchList.Add(key, GetUrlArray(match.Value)[0]);
                    }
                }
            }
            catch (Exception ex)
            {
                matchList.Add(ex.Message, "");
            }
            return matchList;
        }


        /// <summary>
        /// 获取网页源码
        /// </summary>
        /// <param name="url">要获取源码的网页地址</param>
        /// <param name="coding">编码</param>
        /// <returns>返回获取的网页源代码</returns>
        public static string GetPageSourceByUrl(string url, string coding = "gb2312")
        {
            return GetPageSourceByUrl(new Uri(url), coding);
        }

        /// <summary>
        /// 获取网页源码
        /// </summary>
        /// <param name="url">要获取源码的网页地址</param>
        /// <param name="coding">编码</param>
        /// <returns>返回获取的网页源代码</returns>
        public static string GetPageSourceByUrl(Uri url, string coding = "gb2312")
        {
            string getSource = string.Empty;
            try
            {
                
                HttpWebRequest httpwebrequest = (HttpWebRequest)WebRequest.Create(url);
                HttpWebResponse httpwebresponse = (HttpWebResponse)httpwebrequest.GetResponse();
                Stream stream = httpwebresponse.GetResponseStream();
                httpwebrequest.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Maxthon; .NET CLR 1.1.4322)";
                httpwebrequest.Method = "GET";
                StreamReader streamreader = new StreamReader(stream, Encoding.GetEncoding(coding));
                getSource = streamreader.ReadToEnd();
                stream.Close();
                httpwebresponse.Close();
            }
            catch (NotSupportedException exception)
            {
                getSource = exception.Message;
            }
            catch (InvalidOperationException exception)
            {
                getSource = exception.Message;
            }
            catch (IOException exception)
            {
                getSource = exception.Message;
            }
            return getSource;
        }

        /// <summary>
        /// 获取页面内容后，用匹配url正则表达式抓取内容中的url
        /// </summary>
        /// <param name="code">列表代码</param>
        /// <returns>返回截取后的URL地址</returns>
        public static List<string> GetUrlArray(string code)
        {
            List<string> urlList = new List<string>();
            Regex regex = new Regex(@"(http://)?[\w-\.]*([\/]?[\w-])+[\w-]*\.(htm|html|shtm|shtml|aspx|asp|php|jsp)+[\w-\=\?]*", RegexOptions.Compiled | RegexOptions.IgnoreCase);
            MatchCollection matches = regex.Matches(code);
            foreach (Match match in matches)
            {
                urlList.Add(match.Value);
            }
            return urlList;
        }
        /// <summary>
        /// 获取内容code中所有都图片地址
        /// </summary>
        /// <param name="code">内容</param>
        /// <returns>返回截取后都图片地址</returns>
        public static Dictionary<string, string> GetImgUrlArray(string content)
        {
            Dictionary<string, string> imgList = new Dictionary<string, string>();
            Regex reg = new Regex(@"<img[\s\S]*?src=(""(?<src>[^']*?)""|'(?<src>[^']*?)'|(?<src>[^>\s]*))[^>]*?>(.*?)");
            MatchCollection m = reg.Matches(content.ToLower());
            foreach (Match match in m)
            {
                string matchValue = match.Groups["src"].Value;
                if (!imgList.ContainsKey(matchValue))
                {
                    imgList.Add(matchValue, matchValue);
                }
            }
            return imgList;
        }
        //获取页面内容后，分析页面中连接地址取到要抓取的url：
        //处理页面标题和链接
        public static string SniffwebCode(string code, string wordsBegin, string wordsEnd)
        {
            string NewsTitle = "";
            Regex regex1 = new Regex("" + wordsBegin + @"(?<title>[\s\S]+?)" + wordsEnd + "", RegexOptions.Compiled | RegexOptions.IgnoreCase);
            for (Match match1 = regex1.Match(code); match1.Success; match1 = match1.NextMatch())
            {
                NewsTitle = match1.Groups["title"].ToString();
            }
            return NewsTitle;

        }
        /// <summary>
        /// 将相对地址转换为绝对地址
        /// </summary>
        /// <param name="relativeAddress">要转换的相对地址</param>
        /// <param name="absoluteAddress">当前网页地址</param>
        /// <returns>返回转换后的地址</returns>
        public static string ConvertToAbsluteUrl(string relativeAddress, string absoluteAddress)
        {
            if (string.IsNullOrEmpty(relativeAddress))
            {
                return string.Empty;
            }
            if (relativeAddress.Contains("://"))
            {
                return relativeAddress;
            }
            if (string.IsNullOrEmpty(absoluteAddress))
            {
                return string.Empty;
            }
            if (!absoluteAddress.Contains("://"))
            {
                return string.Empty;
            }
            Uri baseUrl = new Uri(absoluteAddress);
            Uri webrul = new Uri(baseUrl, relativeAddress);
            return webrul.ToString();
        }
        /// <summary>
        /// 替换所有HTML标签为空
        /// </summary>
        /// <param name="input">The string whose values should be replaced.</param>
        /// <returns>A string.</returns>
        //public static string RemoveHtml(this string input)
        //{
        //    var stripTags = new Regex("</?[a-z][^<>]*>", RegexOptions.IgnoreCase);
        //    return stripTags.Replace(input, string.Empty);
        //}
        public static string getHtml(string url, string charSet)
        {
            
            //创建WebClient实例myWebClient
            WebClient myWebClient = new WebClient();
            // 需要注意的：
            //有的网页可能下不下来，有种种原因比如需要cookie,编码问题等等
            //这是就要具体问题具体分析比如在头部加入cookie
            // webclient.Headers.Add("Cookie", cookie);
            //这样可能需要一些重载方法。根据需要写就可以了

            //获取或设置用于对向 Internet 资源的请求进行身份验证的网络凭据。
            myWebClient.Credentials = CredentialCache.DefaultCredentials;
            //如果服务器要验证用户名,密码
            //NetworkCredential mycred = new NetworkCredential(struser, strpassword);
            //myWebClient.Credentials = mycred;
            //从资源下载数据并返回字节数组。（加@是因为网址中间有"/"符号）
            byte[] myDataBuffer = myWebClient.DownloadData(url);
            string strWebData = Encoding.Default.GetString(myDataBuffer);

            //获取网页字符编码描述信息
            Match charSetMatch = Regex.Match(strWebData, "<meta([^<]*)charset=([^<]*)\"", RegexOptions.IgnoreCase | RegexOptions.Multiline);
            string webCharSet = charSetMatch.Groups[2].Value;
            if (charSet == null || charSet == "")
                charSet = webCharSet;

            if (charSet != null && charSet != "" && Encoding.GetEncoding(charSet) != Encoding.Default)
                strWebData = Encoding.GetEncoding(charSet).GetString(myDataBuffer);
            return strWebData;
        }

    }

}
